import React from 'react';
import ReactDOM from 'react-dom';

import faceRunner, { PageContext, pageLifecycle, pageLifecycleNames } from '@packages/face-runner';
import * as device from '@packages/lib-device';
import history, { historyCache, historyRouter, historyUrl } from '@packages/lib-history';
import modal from '@packages/lib-modal';
import os from '@packages/lib-os';
import router, { matchByHref, matchByPathname, matchScopeLimit } from '@packages/lib-router';
import { localStorage, sessionStorage as snStorage } from '@packages/lib-storage';
import * as libUrl from '@packages/lib-url';
import { getType } from '@packages/lib-utils';
import { loadScript } from '@packages/lib-window';
import { setPageTitle } from '@shared/document';

import { BackHomeNBackTop } from 'components/BackHome';

import Navigation, { shouldRenderNavigation } from './components/Navigation';
import { redirect } from './util/common';
import appBridge from './wptBridge/oldVersion/appBridge';
import BackPageInfo from './backPageInfo';
import fixPopstate from './fixPopstate';
import { execAppJob, jumpToExternal } from './jumpToExternal';
import { commonVisit } from './share';
import Util from './util';

import webRunnerConfig from '../face.config';

import multiHost from '@/main/multiHost';

const isDevelopment = process.env.NODE_ENV === 'development';

let currentIndex =
    Util.query().wpt_history_index ||
    sessionStorage.getItem('wpt_history_index') ||
    (history.location.state && history.location.state.index) ||
    0;

fixPopstate.pushIndex(currentIndex);
// 只对了 android 内核的做了处理
const enableAnimation = device.evaluateGPU();

const ANIMITION_TIME = 200;
const ANIMITION_TIME_PROMISE = ANIMITION_TIME + 50;
const SHARE_SESSION = 'wpt_share_session';

setTimeout(
    () => {
        history.listen((location, action) => {
            if (WPT.goOutside) {
                WPT.goOutside = false;
                return;
            }

            if (location.state) {
                let url = location.state.url;
                let isBack = true;
                // eslint-disable-next-line no-unused-vars
                const { backStep, backUrl, backBeforeUrl, isFirstBack } = WPT.historyInfo;
                let { moveSteps } = WPT.historyInfo;
                const noAnimation = location?.state?.noAnimation || false;

                if (action === 'POP') {
                    moveSteps = 1;
                    fixPopstate.stopFix();
                    const locationIndex = location.state.index || 0;
                    isBack = currentIndex > locationIndex;
                    $(document).trigger('popstate', { isBack, url });

                    if (!isBack) {
                        WPT.move.isForward = true;
                        moveSteps = -1;
                    } else {
                        if (location.pathname + location.search == backUrl) {
                            if (!isFirstBack || isFirstBack == 2) {
                                moveSteps = backStep;
                            }
                            history.replace(url, {
                                index: location.state.index,
                                url: url,
                                noAnimation,
                            });
                        }
                    }

                    currentIndex = locationIndex;
                    router.showPage(url, false, isBack, false, noAnimation, true, moveSteps);
                }
            }
        });
    },
    os.phone ? 50 : 150
);

function togglePage($dom, hide = true) {
    $($dom).toggleClass('root-page-hide', hide);
}

// 在container上添加show/hideList，托管子组件的所有pageShow/Hide方法
function addShowHideList(dom) {
    dom.showHideList = [];
}

// 把页面初始化的路由参数init到dom上,解决路由不准确的问题
function addPageInfo(dom, options = {}) {
    dom.info = options;
}

function reciveJPage(isBack, isLoad, noRecordHistory, defaultRouter, defaultUrl, backNum) {
    // 获得当前有页面的钩子或空的钩子 type : cur || empty
    let passPageNum = 0;
    let $nextPage = null;
    let $passPage = null;
    if (noRecordHistory) {
        // 只有前进 和加载才会有不储存的情况
        passPageNum = $('#J_Page .curPage').data('page') - backNum;
        if (passPageNum <= 0) {
            // 有一点逻辑待完成，--------------------------
            passPageNum = WPT.recordPageLimit;
        }
        $passPage = $(`#J_Page [data-page='${passPageNum}']`);

        $nextPage = $('#J_Page .curPage').data('router', defaultRouter).data('href', defaultUrl);
        return {
            passPage: $passPage[0],
            passPageIndex: $passPage.data('page'),
            nextPage: $nextPage[0],
            nextPageIndex: $nextPage.data('page'),
        };
    }
    $passPage = $('#J_Page .curPage').removeClass('curPage');
    passPageNum = $passPage.data('page');
    let nextPageNum = 1;

    if (!WPT[passPageNum]) {
        WPT[passPageNum] = {};
    }
    $passPage.data('scroll', $(window).scrollTop());

    if (isBack && !isLoad) {
        nextPageNum = passPageNum - backNum;
        if (nextPageNum <= 0) {
            if (backNum != 1) {
                nextPageNum = passPageNum + 5 - backNum;
            } else {
                nextPageNum = WPT.recordPageLimit;
            }
        }
    } else {
        if (WPT.historyInfo.moveSteps < 0) {
            nextPageNum = passPageNum + -WPT.historyInfo.moveSteps;
        } else {
            nextPageNum = passPageNum + 1;
        }
        if (nextPageNum > WPT.recordPageLimit) {
            nextPageNum = 1;
        }
    }

    // console.log('nextPageNum', nextPageNum, 'backNum', backNum);

    $nextPage = $(`#J_Page [data-page='${nextPageNum}']`);
    if (!$nextPage.length) {
        $nextPage = $(`<div id="Page" data-page="${nextPageNum}"></div>`);
        $('#J_Page').append($nextPage);
    }
    $nextPage.addClass('curPage');
    togglePage($nextPage, false);
    $nextPage.data('router', defaultRouter);
    $nextPage.data('href', defaultUrl);

    // WPT.$curPage = $nextPage;
    if (WPT[passPageNum] && WPT[passPageNum].hide) {
        const hideObject = WPT[passPageNum].hide;
        Object.keys(hideObject).forEach((key) => {
            $.isFunction(hideObject[key]) && hideObject[key]();
        });
    }
    if (WPT[nextPageNum] && WPT[nextPageNum].show) {
        const showObject = WPT[nextPageNum].show;
        Object.keys(showObject).forEach((key) => {
            $.isFunction(showObject[key]) && showObject[key]();
        });
    }

    return {
        passPage: $passPage[0],
        passPageIndex: $passPage.data('page'),
        nextPage: $nextPage[0],
        nextPageIndex: $nextPage.data('page'),
    };
}

// 管理延迟定时器
const TimeOutManager = (function TOM() {
    let allData = {};
    function append(fun, time) {
        if (time > 0) {
            const num = setTimeout(() => {
                delete allData[num];
                fun();
            }, time);
            allData[num] = fun;
        } else {
            fun();
        }
    }
    function run() {
        Object.keys(allData).forEach((k) => {
            window.clearTimeout(k);
            allData[k]();
        });
        allData = {};
    }
    return {
        append,
        run,
        allData,
    };
})();

/**
 * 异步可中断任务
 * @class AsyncJob
 */
class AsyncJob {
    constructor(fn) {
        this.isStop = false;
        this.fn = fn;
    }

    stop = () => {
        if (!this.isStop) {
            this.isStop = true;
            console.log('异步任务被取消');
        }
    };

    exec = () => {
        !this.isStop && this.fn && this.fn();
        this.isStop = true;
    };
}
/**
 * 支付类页面需要使用强制跳转，如果使用内部跳转的话，会导致微信支付报错
 * @param {string} url
 * @returns {boolean}
 */
function forceRedirect(url = '') {
    return false;
}

function renderPage(PageComp, props, dom, callback) {
    if (isDevelopment && !PageComp.prototype.isReactComponent) {
        throw new Error(`页面级根组件必须是class组件: ${PageComp}`);
    }
    Object.assign(props, {
        $dom: dom,
        // LazyImage 预览缓存
        previewCache: {},
    });

    const PC_MODE = os.pc && PageComp.pageConfig?.mode === 'pc';
    dom.classList.toggle('pageMode-pc', PC_MODE);

    if (PageComp.pageConfig && PageComp.pageConfig.domBackgroundColor) {
        if (typeof PageComp.pageConfig.domBackgroundColor === 'function') {
            dom.style.backgroundColor = PageComp.pageConfig.domBackgroundColor();
        } else {
            dom.style.backgroundColor = PageComp.pageConfig.domBackgroundColor;
        }
    } else {
        dom.style.backgroundColor = '#f4f6f6';
    }

    // use math.random 避免组件复用
    ReactDOM.render(
        <PageContext.Provider value={props}>
            {shouldRenderNavigation() && <Navigation key={Math.random()} PageComp={PageComp} />}
            <PageComp
                {...props}
                ref={(ele) => {
                    // ele为null时，表示组件被卸载
                    ele && callback(ele);
                }}
            />
            {!PC_MODE && (
                <>
                    <BackHomeNBackTop pageConfig={PageComp.pageConfig} key={Math.random()} />
                </>
            )}
        </PageContext.Provider>,
        dom
    );
}

// 作为showPage isLoad 的interface
// eslint-disable-next-line no-unused-vars
const showPageInterface = {
    // eslint-disable-line
    // 是否第一次加载
    isLoad: false,
    // 是否是返回
    isBack: false,
    // 强制使用网页
    jumpToWeb: false,
    // 不使用动画
    noAnimation: false,
    // 不记录历史，相当于replace
    noRecordHistory: false,
    // 强制替换r
    enforceR: false,
    // query参数
    query: null,
};

// 可取消异步任务
let prevAsyncJob;

// 基础链接的转换
router.hooks.setupShowPage.tapAsync('base', async function (...args) {
    let [url, isLoad, isBack, noRecordHistory, noAnimation, jumpToWeb, backNum] = args;
    let enforceR = false;
    if (getType(isLoad) === 'object') {
        const config = isLoad;
        isLoad = config.isLoad;
        isBack = config.isBack;
        noRecordHistory = config.noRecordHistory;
        noAnimation = config.noAnimation;
        jumpToWeb = config.jumpToWeb;
        backNum = config.backNum;
        enforceR = config.enforceR;

        if (config.query && getType(config.query) === 'object') {
            url = libUrl.params(url, config.query);
        }
    }

    if (os.wechatPC) {
        noAnimation = true;
    }

    if (isLoad && libUrl.query(url).sf) {
        // 第一次加载并且链接上有sf
        snStorage.setItem(SHARE_SESSION, libUrl.query(url).sf);
    }

    // app和小程序传来的sessionId在这里处理设置到cookie上
    const { wjhSessionId: sessionId } = libUrl.query(url);
    if (sessionId) {
        WPT.setCookie('wptSessionId', sessionId);
    }
    if (!isLoad && forceRedirect(url)) {
        return;
    }
    if (!isLoad && !isBack && !enforceR) {
        // 新统计特殊处理
        const urlQuery = libUrl.query();
        // const { r, fr, c } = urlQuery;

        const from = {};
        // if (r) {
        //     from.r = r;
        // }
        // if (fr) {
        //     from.fr = fr;
        // }
        // if (c) {
        //     // 新版统计上报新加的和r一样的参数
        //     from.c = c;
        // }
        // 业务透传参数
        Object.keys(urlQuery).forEach((key) => {
            if (key.indexOf('fr_') === 0) {
                from[key] = urlQuery[key];
            }
        });

        url = libUrl.handleUrl(from, url);
    }

    return [url, isLoad, isBack, noRecordHistory, noAnimation, jumpToWeb, backNum];
});

// 多域名支持仅针对特定路由
router.hooks.beforeShowPage.tap('multi-host', multiHost);

router.hooks.beforeShowPage.tap('main-base', (...args) => {
    // 有异步任务，就终结掉
    prevAsyncJob && prevAsyncJob.stop();

    const [url, isLoad, isBack, , , jumpToWeb] = args;

    if (!jumpToWeb && jumpToExternal(url, true)) {
        // 跳外部去了
        return true;
    }
    /**
     * app 端，如果是打开新的 webView
     * 则直接调用 wptJumpNativeWithUrl
     * 并且传参数 isOpenNewWebView=1
     */
    if (!isLoad && os.wpt && libUrl.query().isOpenNewWebView) {
        const { isOpenNewWebView, ...otherParams } = libUrl.query();

        const _url = libUrl.params(window.location.origin + url.split('?')[0], { ...otherParams });
        execAppJob(() => {
            appBridge.jump(_url, () => {}, {
                ...libUrl.query(),
            });
        });

        return true;
    }

    // 前后两次url相同，或者 pathname query相同
    if (WPT.curUrl === url || libUrl.diff(WPT.curUrl, url)) {
        // 3.0 todo
        console.warn('不能重复切换相同页面');
        // 通知组件url发生变化
        if (WPT.$curPage && WPT.$curPage[0]) {
            const { showHideList = [] } = WPT.$curPage[0];
            showHideList.forEach((i) => i.onPopState && i.onPopState(isBack));
        }

        pageLifecycle.emit({ name: pageLifecycleNames.popState });
        return true;
    }
});

router.hooks.afterShowPage.tap('main-base', (...args) => {
    router.set('useNormalizeLive', true);
    /**
     * 是否使用 faceRunner 加载
     */
    let useWebRunner = false;
    const [, isLoad, isBack, noRecordHistory, noAnimation, jumpToWeb, backNum] = args;
    let [url] = args;

    // 如果 setupShowPage 调整后的地址为空，则什么也不做
    if (!url) {
        return;
    }

    url = libUrl.removeUrlOrigin(url);

    TimeOutManager.run();
    let isBackAndRender = false;
    let matchResult = {};
    // 暂存props供下文使用
    let pageProps = {};

    function replacePage(options) {
        const { pageRouter, page, params } = options;
        const isAndroid = (os.android && !enableAnimation) || noAnimation;
        const NA = isAndroid || WPT.move.isMove || os.pc;
        const nextPage = page.nextPage; // 获得不在使用的页面
        const passPage = page.passPage; //
        const $nextPage = $(nextPage);
        const $passPage = $(passPage);
        const nextPageKey = `Page-${$nextPage.data('page')}`;

        // react root element需要的props
        pageProps = {
            url, // 当前url
            href: `${window.location.origin}${url}`,
            router: matchResult.router,
            // pageName: `${window.location.origin}${pageNameConfig[matchResult.router] || matchResult.router}`,
            referer: WPT.referrer || document.referrer || '',
            referrer: WPT.referrer || document.referrer || '',
            params,
            query: Util.query(url),
            key: Date.now(),
            sf: snStorage.getItem(SHARE_SESSION) || '',
        };

        WPT.$curPage = $(nextPage);

        if (isBack && !isLoad) {
            // 如果是回退  新页 面放在下面。  否则新页面在上面
            nextPage.style.zIndex = 0;
            $passPage.css({ zIndex: 1, position: 'fixed', top: `${-$(window).scrollTop()}px` });
            // 执行动画
            !NA &&
                TimeOutManager.append(() => {
                    passPage.clientHeight; // eslint-disable-line
                    $passPage.addClass('flip-left');
                }, 100);

            if (nextPage.innerHTML.length < 50) {
                // 回退发现没数据了 说明页面被清理了
                isBackAndRender = true;
                addShowHideList(nextPage);
                addPageInfo(nextPage, pageProps);
                renderPage(WPT.allPage[pageRouter], pageProps, nextPage, (instance) => {
                    WPT[nextPageKey] = instance;
                    device.hideOptionMenu();
                    setPageTitle(instance);
                });
            } else {
                device.hideOptionMenu();
                setPageTitle(WPT[nextPageKey]);
            }

            TimeOutManager.append(
                () => {
                    nextPage.style.zIndex = 1;
                    if (passPage) {
                        $passPage.removeClass('flip-left');
                        togglePage(passPage);
                        $passPage.css({ zIndex: 0, position: 'relative', top: '0' });
                        WPT.clearPage($passPage.data('page'));
                    }
                },
                NA ? 0 : ANIMITION_TIME_PROMISE
            );

            // 滚动滚动条
            TimeOutManager.append(
                () => {
                    nextPage.clientHeight; // eslint-disable-line
                    $(window).scrollTop($nextPage.data('scroll'));
                },
                NA ? 0 : 50
            );
        } else {
            nextPage.style.zIndex = 1;
            passPage && (passPage.style.zIndex = 0);

            if (!isLoad) {
                // 非回退 并且是页面切换
                nextPage.style.cssText = ';position: fixed; z-index: 1; top: 0;';
            }

            if (!WPT.allPage[pageRouter]) {
                const date = new Date();
                if (sessionStorage.getItem('WPT-reload-time') !== `${date.getHours()}-${date.getMinutes()}`) {
                    sessionStorage.setItem('WPT-reload-time', `${date.getHours()}-${date.getMinutes()}`);
                    window.location.reload();
                }
                return;
            }

            addShowHideList(nextPage);
            addPageInfo(nextPage, pageProps);

            // 页面渲染
            renderPage(WPT.allPage[pageRouter], pageProps, nextPage, (instance) => {
                WPT[nextPageKey] = instance;
                device.hideOptionMenu();
                setPageTitle(instance);
            });
            // 强制浏览器reflow，然后执行动画
            nextPage.clientHeight; // eslint-disable-line
            if (isLoad) {
                // $nextPage.addClass('fadeIn');
                // TimeOutManager.append(() => {
                //     $nextPage.removeClass('fadeIn');
                // }, 1000);
            } else {
                // 页面切换动画
                !NA && $nextPage.addClass('flip-right');
                TimeOutManager.append(
                    () => {
                        togglePage(passPage);
                        TimeOutManager.append(
                            () => {
                                $(window).scrollTop(0);
                                $nextPage.removeClass('flip-right'); // .className = "";
                                nextPage.style.position = 'relative';
                            },
                            NA ? 0 : 100
                        );
                    },
                    NA ? 0 : ANIMITION_TIME_PROMISE
                );
            }
        }

        // 调用组件hide/show方法
        const passReact = WPT[`Page-${$passPage.data('page')}`];
        if (passReact && passReact.hide) {
            passReact.hide();
        }
        // 触发子组件的hide callback
        passPage &&
            passPage.showHideList &&
            passPage.showHideList.forEach((instance) => {
                $.isFunction(instance.onPageHide) && instance.onPageHide();
            });

        const nextReact = WPT[`Page-${$nextPage.data('page')}`];
        !isLoad &&
            isBack &&
            !isBackAndRender &&
            TimeOutManager.append(() => {
                // 非加载的时候执行
                if (nextReact && nextReact.show) {
                    nextReact.show();
                }
                // 触发子组件的show callback
                nextPage &&
                    nextPage.showHideList &&
                    nextPage.showHideList.forEach((instance) => {
                        $.isFunction(instance.onPageShow) && instance.onPageShow();
                    });
            }, ANIMITION_TIME);

        (isBack || isLoad) &&
            TimeOutManager.append(() => {
                // 非加载的时候执行
                $(window).scrollTop($(window).scrollTop() + 0.1);
            }, ANIMITION_TIME);

        WPT.move = {};
        WPT.isScroll = false; // todo WPT.onTouchEnd里有牵连

        setTimeout(() => {
            WPT.goOutside = false;
        }, ANIMITION_TIME);
    }

    function callBack(pageRouter, params) {
        WPT.Model.clear();
        modal && modal.closeAll();

        const { state = {} } = window.history.state || {};
        const index = Number(state.index) || 0;

        if (!isBack) {
            // 前进
            if (noRecordHistory) {
                history.replace(url, { url, noAnimation, index: currentIndex });
            } else {
                !WPT.move.isForward && WPT.pushState(url, noAnimation);
                // 进入没有历史的页面index才需要+1，返回前进的不需要
                WPT.move.isForward && sessionStorage.setItem('wpt_history_index', index);
            }
        } else {
            sessionStorage.setItem('wpt_history_index', index);
        }

        WPT.curUrl = url;
        WPT.curRouter = pageRouter;

        if (pageRouter === '/home') {
            WPT.wptCloseBtnHandel(1);
        } else {
            WPT.wptCloseBtnHandel(0);
        }

        if (!isBack) {
            // 不是回退的时候 清理
            sessionStorage.removeItem(pageRouter);
            if (!noRecordHistory || isLoad) {
                // 记录历史的 || 加载 放进去
                historyRouter.push(pageRouter);
                historyUrl.push({ router: pageRouter, url });
                historyCache.push(url);
            }
            if (noRecordHistory) {
                historyRouter.splice(historyRouter.length - 1, 1, pageRouter);
                historyUrl.splice(historyUrl.length - 1, 1, { router: pageRouter, url });
                historyCache.splice(historyCache.length - 1, 1, url);
            }
        } else if (historyRouter.length <= 1) {
            // 如果返回的时候历史小于2 说明当前页面刷新过，
            if (backNum && Math.abs(backNum) >= 2) {
                console.log('返回页面超过2页');
            } else {
                historyRouter.length = 0;
                historyRouter.push(pageRouter);
                historyUrl.length = 0;
                historyUrl.push({ router: pageRouter, url });
                historyCache.length = 0;
                historyCache.push(url);
            }
        } else {
            const backHistoryNum = WPT.historyInfo.isFirstBack == 1 ? 1 : backNum;
            if (Math.abs(backNum) > 1) {
                WPT.historyInfo.isFirstBack = 1;
                BackPageInfo.setFirstBack(1);
            }
            historyRouter.splice(historyRouter.length - backHistoryNum, backHistoryNum);
            historyUrl.splice(historyUrl.length - backHistoryNum, backHistoryNum);
            historyCache.splice(historyCache.length - backHistoryNum, backHistoryNum);
            if (!$.isEmptyObject(historyUrl)) {
                const curdata = historyUrl[historyUrl.length - 1 - backNum] || {};
                const a = document.createElement('a');
                a.href = curdata.url;
                WPT.setRefer(curdata.url ? a.href : '');
            }
        }

        // sessionStorage.setItem('historyUrl', JSON.stringify(historyUrl));
        // sessionStorage.setItem('historyRouter', JSON.stringify(historyRouter));
        sessionStorage.setItem('historyCache', JSON.stringify(historyCache));

        $(document).trigger('Page:change', [{ url, router: pageRouter }]);
        modal.loading.close();

        if (useWebRunner) {
            console.warn('web runner 模式', pageRouter);
            const PageComponent = WPT.allPage[pageRouter];
            faceRunner.render({
                PageComponent,
                isLoad,
                isBack,
                noAnimation,
                noRecordHistory,
                router: pageRouter,
                params,
                href: url,
            });
        } else {
            // console.warn('普通模式', pageRouter);
            const page = reciveJPage(isBack, isLoad, noRecordHistory, pageRouter, url, backNum); // 获得不在使用的页面
            const { passPageIndex, nextPageIndex } = page;
            // 切换页面后, 触发 faceRunner 渲染过的页面 onHide 事件
            // pageLifecycle 内部会判断是否存在过该页面
            if (passPageIndex) {
                pageLifecycle.emit({ name: pageLifecycleNames.hide, pageKey: passPageIndex });
            }

            // 清空 faceRunner 模式下的实例缓存, 同时生成一个空的队列, 用于在 initHtml 方法中替代
            pageLifecycle.pageKey = nextPageIndex;
            pageLifecycle.initPage();

            // 页面切换，渲染
            replacePage({ pageRouter, page, params });
        }

        // 安卓版微信或者企业微信
        if (!isLoad && (os.android || os.wxwork)) {
            WPT.wxConfigInit();
        }
        commonVisit(isBack, pageProps);
    }

    matchResult = matchByPathname(url, WPT.router);
    if (!matchResult) {
        if (process.env.NODE_ENV !== 'production' && process.env.LOCAL) {
            modal.loading('编译中...');
            $.ajax({
                type: 'GET',
                url: `${WPT.loadScriptHost}/compile?url=${encodeURIComponent(
                    url.replace(/^\/h5\//i, '/')
                )}&t=${Date.now()}`,
                dataType: 'json',
                success: (res) => {
                    const { status } = res;
                    if (status === 'not found') {
                        modal && modal.closeAll();
                        modal.alert('路由不存在');
                    } else if (status === 'done') {
                        loadScript(`${WPT.loadScriptHost}/webApp/router.js?time=${new Date().getTime()}`, () => {
                            router.showPage(url, isLoad, isBack, noRecordHistory, noAnimation, jumpToWeb);
                        });
                    }
                },
                error(e) {
                    modal && modal.closeAll();
                    console.error(e);
                },
            });
        } else {
            console.error(`${url} 不存在`);
        }
        return;
    }

    // 根据当前页面的  chunkNumber 判断是否使用 faceRunner 渲染
    const { router: pageRouter, value: config, params } = matchResult;
    const pathChunkName = config.path.replace('/webApp/dist/', '');
    useWebRunner = webRunnerConfig?.views?.some((chunkName) => pathChunkName.startsWith(chunkName));

    // 不是第一次加载，匹配404，使用外部跳转。避免访问不到最新页面
    if (!isLoad && pageRouter === '*') {
        window.location.href = Util.urlAddQuery(url, { from404Match: 1 });
        return;
    }

    prevAsyncJob = new AsyncJob(() => {
        // 页面block 400ms
        callBack(pageRouter, params);
    });

    // 执行页面切换的时候，应该阻止用户手动操作
    if (WPT.allPage[pageRouter]) {
        prevAsyncJob.exec();
        return;
    }
    modal.loading('正在加载中...', { delay: 1000 });

    // 异步事件
    // 如果没有加载完毕，就又触发了showPage，那应该取消下次任务的执行，如何取消呢？
    loadScript(config.path, prevAsyncJob.exec);
});

function segment(n) {
    const pathname = window.location.pathname;
    const urlList = pathname.replace(/(^\/)|(\/$)/g, '').split('/');
    if (urlList[n] !== undefined) {
        return urlList[n];
    }
    return '';
}

function pushState(curUrl, noAnimation) {
    if (window.history.pushState) {
        if (!curUrl) {
            console.warn('warn： page after the jump not history.pushState last page');
        } else {
            WPT.setRefer(window.location.href);
            const { state = {} } = window.history.state || {};
            const index = Number(state.index) || 0;
            history.replace(WPT.curUrl, { url: WPT.curUrl, noAnimation, index });
            currentIndex = index + 1;
            sessionStorage.setItem('wpt_history_index', currentIndex);
            history.push(curUrl, { url: curUrl, index: currentIndex });
            fixPopstate.pushIndex(currentIndex);
        }
    }
}

/**
 * 替换 url
 * @exports WPT/replaceUrl
 * @param {String} url 页面 url
 */
const replaceUrl = (url) => {
    WPT.curUrl = url;
    history.replace(WPT.curUrl, { url: WPT.curUrl, index: currentIndex });
    WPT.$curPage.data('href', url); // 保持dom上挂载的href同步
};

/**
 * 获取root props
 * @exports WPT/getRootProps
 * @returns {Object}
 */
const getRootProps = () => {
    const current = WPT[`Page-${WPT.$curPage.data('page')}`];

    return current ? current.props : null;
};

window.addEventListener(
    'pagehide',
    () => {
        if (WPT.serverLoginTime > 1541692800 && WPT.serverLoginTime < 1541779200) {
            // 时间11.9 00--11.9 24:00
            localStorage.setItem('showIcon119', 1, 86400); // 双11活动，页面销毁后就不在显示活动icon
        }
    },
    false
);

window.addEventListener('pageshow', (e) => {
    // 通过persisted属性判断是否存在 BF Cache
    if (!e.persisted || !WPT.$curPage) {
        return;
    }
    const current = WPT[`Page-${WPT.$curPage.data('page')}`];
    if (!current) {
        return;
    }
    WPT.$curPage[0]?.showHideList?.forEach((instance) => {
        $.isFunction(instance.onWindowShow) && instance.onWindowShow(e);
    });
});

export { segment, pushState, replaceUrl, getRootProps };
